<template>
  <div>
    <el-card>
      <Search ref="searchRef" :search="search" :config="imageData.character.config" @search="onSearch" @open-add="loadCharacters" @pageChange="onTablePageChange" @export="handleExport"
      @import-images="openImageImportDialog" @import="handleImport" @delete-disliked="handleDeleteDisliked" @delete-filter="handleDeleteFilter"></Search>
      <CharacterBox  v-loading="imageData.character.config.loading" v-bind="imageData.character"
         @del-row="handleDelCharacter" @edit="handleEditCharacter" 
        @replace-image="handleImageChange" @load-characters="loadCharacters" ></CharacterBox>
    </el-card>
    <el-drawer v-model="imageData.character.isOpen" size="100%" :with-header="false">
          <el-card>
    <el-form ref="characterForm" :model="character">
      <el-form-item :label="$t('message.character.name')" prop="name" :rules="[{ required: true, message: $t('message.character.name'), trigger: 'blur' }]">
        <el-input v-model="character.name" type="text" :placeholder="$t('message.character.name')"></el-input>
      </el-form-item>
      <el-form-item :label="$t('message.character.customName')" prop="cn_name" :rules="[{ required: true, message: $t('message.character.customName'), trigger: 'blur' }]">
        <el-input v-model="character.cn_name" type="text" :placeholder="$t('message.character.customName')"></el-input>
      </el-form-item>
      <el-form-item :label="$t('message.character.tag')" prop="tag" :rules="[{ required: true, message: $t('message.character.tag'), trigger: 'blur' }]">
        <el-input v-model="character.tag" type="text" :placeholder="$t('message.character.tag')"></el-input>
      </el-form-item>
    </el-form>
    <el-row style="justify-content: center">
      <el-image :src="character.image" style="width: 200px;object-fit: contain;" fit="contain" hide-on-click-modal
        :preview-src-list="[character.image]">
        <template #toolbar="{ actions, activeIndex }">
          <!-- 自定义工具栏 -->
          <div class="custom-viewer-toolbar">
            <el-button size="default" @click="actions.reset">
              <el-icon>
                <ZoomOut />
              </el-icon>
            </el-button>

            <!-- 下载按钮 -->
            <el-button size="default" @click="generationStore.handleDownload(character.image)">
              <el-icon>
                <Download />
              </el-icon>
            </el-button>

            <el-button size="default" @click="actions.prev">
              <el-icon>
                <ArrowLeft />
              </el-icon>
            </el-button>

            <el-button size="default" @click="actions.next">
              <el-icon>
                <ArrowRight />
              </el-icon>
            </el-button>
          </div>
        </template>
      </el-image>
    </el-row>
    <template #footer>
      <el-row>
        <el-button style="margin-bottom: 5px; margin-right: 10px" type="primary" @click="addCharacter"
          icon="Plus">{{ $t('message.common.add') }}</el-button>
        <el-upload action="#" accept=".jpg,.jpeg,.png" :auto-upload="false" :show-file-list="false"
          :on-change="handleFileChange">
          <el-button type="primary">{{ $t('message.character.imageUpload') }}</el-button>
          <template #tip>
            <div class="el-upload__tip">{{ $t('message.character.imageUploadTip') }}</div>
          </template>
        </el-upload>
      </el-row>
    </template>
  </el-card>
    </el-drawer>
    <el-dialog
      v-model="taskStatus.progressVisible"
      :title="`${taskStatus.type === 'import' ? '导入' : '导出'}进度`"
      width="300px"
      :close-on-click-modal="false"
      :show-close="false"
    >
      <div class="task-progress">
        <el-progress
          :percentage="taskStatus.progress"
          stroke-width="6"
          :status="taskStatus.progress === 100 ? 'success' : 'active'"
        />
        <p class="progress-text">{{ taskStatus.progress }}%</p>
        <p v-if="taskStatus.progress < 100" class="progress-info">
          正在{{ taskStatus.type === 'import' ? '导入' : '导出' }}数据，请稍候...
        </p>
        <p v-if="taskStatus.progress === 100" class="progress-info">
          {{ taskStatus.type === 'import' ? '导入' : '导出' }}完成
          <span v-if="taskStatus.type === 'export'">，即将下载文件</span>
        </p>
      </div>
    </el-dialog>
    <el-dialog
      v-model="imageImportDialog.visible"
      title="批量导入角色图片"
      width="500px"
    >
      <el-upload
        ref="imageBatchUploader"
        action="#"
        accept=".jpg,.jpeg,.png,.txt"
        :multiple="true"
        :auto-upload="false"
        :show-file-list="false"
        :on-change="handleBatchFileChange"
        :file-list="imageImportDialog.fileList"
      >
        <el-button type="primary">选择图片和文本文件</el-button>
        <template #tip>
          <div class="el-upload__tip">
            支持JPG、PNG图片文件和TXT文本文件（图片文件名需与文本文件名对应）
          </div>
        </template>
      </el-upload>
      
      <template #footer>
        <el-button @click="imageImportDialog.visible = false">取消</el-button>
        <el-button type="primary" @click="confirmImageImport">确认导入</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts" name='CharacterPanel'>
import { ElMessage, ElMessageBox, FormInstance } from 'element-plus';
import { computed, defineAsyncComponent,  onMounted,  reactive, ref } from 'vue';
import { useGenerationStore } from '@renderer/stores/useGenerationStore'
import { useConfigStore } from '@renderer/stores/configStore';
import { characterApi } from '@renderer/api/character';
import { useI18n } from 'vue-i18n';
import { ipcService } from '@renderer/services/ipcService';
import { translateApi } from '@renderer/api/translate';

const { t } = useI18n()
const Search = defineAsyncComponent(() => import('@renderer/views/random/component/Search.vue'))
const CharacterBox = defineAsyncComponent(() => import('@renderer/views/random/component/CharacterBox.vue'))
const searchRef = ref(null)
const configStore = useConfigStore()
const generationStore = useGenerationStore()
const characterForm = ref<FormInstance | null>(null)
const character = reactive({
  name: '',
  cn_name: '',
  tag: '',
  image: '',
})

const taskStatus = reactive({
  type: 'import' as 'import' | 'export', // 任务类型：导入/导出
  loading: false, // 任务加载状态
  progressVisible: false, // 进度对话框显示状态
  progress: 0, // 进度百分比
  taskId: '', // 当前任务ID
  progressTimer: null as NodeJS.Timeout | null // 进度查询定时器
});

const imageData = reactive({
  character: {
    data: [],
    config: {
      total: 0, // 列表总数
      loading: false, // loading 加载
      isBorder: false, // 是否显示表格边框
      isSerialNo: false, // 是否显示表格序号
      isSelection: false, // 是否显示表格多选
      isOperate: true, // 是否显示表格操作栏
      isToolTip: true
    },
    param: {
      page: 1,
      page_size: 20,
      
    },
    isOpen: false,
  },
  getUrl: 'sql/get_character_paged',
  exportUrl: 'sql/export_character_stream',
})

const search = computed(()=>[
      { label: '人物名称', prop: 'name', placeholder: t('message.character.name'), required: false, type: 'input' },
      { label: '中文', prop: 'cn_name', placeholder: t('message.character.customName'), required: false, type: 'input' },
      {
        label: t('message.random.favorite'),
        prop: 'favorite',
        placeholder: t('message.random.favorite'),
        required: false,
        type: 'select',
        options: [
          {
            label: 'All',
            value: ''
          },
          {
            label: 'true',
            value: 1
          },
          {
            label: 'false',
            value: 0
          }
        ]
      },
      {
        label: t('message.random.disliked'),
        prop: 'disliked',
        placeholder: t('message.random.disliked'),
        required: false,
        type: 'select',
        options: [
          {
            label: 'All',
            value: ''
          },
          {
            label: 'true',
            value: 1
          },
          {
            label: 'false',
            value: 0
          }
        ]
      }
    ])

const sanitizeFilename = (name: string) => {
  if (!name) return 'untitled';
  let sanitized = name.replace(/[/\\?%*:|"<>]/g, '_');
  return sanitized;
};

const addCharacter = async () => {
  try {
    // 使用可选链 + 类型断言
    await characterForm.value?.validate(async (valid) => {
      if (valid) {
        if (character.image) {
          characterApi().addCharacter({ name: character.name, cn_name: character.cn_name, tag: character.tag, image: character.image }).then(res => {
            ElMessage.success(JSON.stringify(res.data))
          })
        }
        else {
          ElMessage.error("图片不能为空")
        }
      }
    })
  } catch (error) {
    ElMessage.error('验证失败:')
  }
}

const handleFileChange = async (uploadFile) => {
  try {
    // 文件验证
    if (!['image/jpeg', 'image/png', 'image/jpg'].includes(uploadFile.raw.type)) {
      ElMessage.error('仅支持 JPG/JPEG/PNG 格式');
      return;
    }

    if (uploadFile.raw.size > 5 * 1024 * 1024) {
      ElMessage.error('文件大小不能超过5MB');
      return;
    }

    // 转换为WebP
    const webpData = await configStore.convertToWebpV2(uploadFile.raw);
    character.image = webpData as string;
    ElMessage.success('转换成功！');
  } catch (error) {
    ElMessage.error(`转换失败: ${error.message}`);
  }
};

const getTableData = () => {
  imageData.character.config.loading = true
  characterApi().getCharacterList(imageData.character.param).then(res => {
    imageData.character.data = res.data.data
    imageData.character.config.total = res.data.pagination.total
    imageData.character.param.page = res.data.pagination.page
  }).finally(() => {
    imageData.character.config.loading = false
  })
};

const handleDelCharacter = async (name: string) => {
  try {
    await ElMessageBox.confirm('确定删除该标签？', '警告', { type: 'warning' })
    characterApi().deleteCharacter({ name: name }).then(res => {
      ElMessage.success(JSON.stringify(res.data))
      getTableData()
    })
  } catch (error) {
    // 用户取消不处理
  }
}

const handleDeleteDisliked = async ()=>{
  try {
    await ElMessageBox.confirm('确定删除标记标签？', '警告', { type: 'warning' })
    characterApi().deleteDislikedCharacter().then(res => {
      if(res.data.result){
        ElMessage.success("删除成功")
        getTableData()
      }
      else{
        ElMessage.error(JSON.stringify(res.data))
      }
    })
  } catch (error) {
    // 用户取消不处理
  }
}

const handleDeleteFilter = async (data)=>{
  try {
    await ElMessageBox.confirm('确定删除当前筛选的角色？', '警告', { type: 'warning' })
    characterApi().deleteCharactersByFilter(data).then(res => {
      if(res.data.success){
        ElMessage.success(JSON.stringify(res.data))
        getTableData()
      }
      else{
        ElMessage.error(JSON.stringify(res.data))
      }
    })
  } catch (error) {
    // 用户取消不处理
  }
}

const handleEditCharacter = (image: any) => {
  characterApi().updateCharacter(image).then(res => {
    if(res.data.data){
      ElMessage.success("标记状态已变更")
    }
    getTableData()
  })
}

const handleImageChange = async (imageName:string,file:File) => {
  try {
    const replaceName = sanitizeFilename(imageName)
    const imageSave = `${configStore.config.imagesPath}\\character\\${replaceName}.webp`
    const result = await ipcService.saveWebpImage(
      file,
      imageSave
    )
    if (result.success) {
      ElMessage.success('图片保存成功');
      configStore.updateImageVersion(imageSave);    
      getTableData();
    } else {
      ElMessage.warning('图片保存失败，但记录已创建');
    }
  } catch (error) {
    ElMessage.error(`图片保存失败: ${error.message}`);
  }
}

// 分页改变时回调
const onTablePageChange = (page: any) => {
  imageData.character.param.page = page.pageNum;
  imageData.character.param.page_size = page.pageSize;
  getTableData();
};



const onSearch = (data: any) => {
  imageData.character.param = Object.assign({}, imageData.character.param, { ...data });
  searchRef.value.pageReset()
};

const loadCharacters = () => {
  imageData.character.isOpen = true
}

const handleExport = async (data:any) => {
  try {
    taskStatus.type = 'export';
    taskStatus.loading = true;
    taskStatus.progress = 0;
    taskStatus.progressVisible = true;
    taskStatus.taskId = `export_${Date.now()}`;

    taskStatus.progressTimer = setInterval(() => {
      if (taskStatus.progressVisible && taskStatus.taskId) {
        fetchTaskProgress();
      }
    }, 200);
    // 调用导出接口
    const params = {
      ...data,
      taskId: taskStatus.taskId
    };

    const response = await characterApi().exportCharacterStream(params);
    const url = window.URL.createObjectURL(new Blob([response.data]));
    const link = document.createElement('a');
    link.href = url;
    link.setAttribute('download', `character_${new Date().getTime()}.csv`);
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);

    // 清除定时器并最后一次查询进度
    clearProgressTimer();
    await fetchTaskProgress();
  } catch (error) {
    console.error('导出失败:', error);
    ElMessage.error('导出失败，请重试');
    clearProgressTimer();
    taskStatus.progressVisible = false;
  } finally {
    // 确保最终状态重置
    if (taskStatus.progress === 100 || taskStatus.progress === -1) {
      taskStatus.loading = false;
    }
    clearProgressTimer();
  }
};

const handleImport = async (file: File) => {
  try {
    taskStatus.type = 'import';
    taskStatus.loading = true;
    taskStatus.progress = 0;
    taskStatus.progressVisible = true;
    taskStatus.taskId = `import_${Date.now()}`;
    
    // 启动进度查询定时器（保持运行直到任务结束）
    taskStatus.progressTimer = setInterval(() => {
      if (taskStatus.progressVisible && taskStatus.taskId) {
        fetchTaskProgress();
      }
    }, 200);

    // 使用FormData携带文件和参数
    const formData = new FormData();
    formData.append('file', file);
    formData.append('taskId', taskStatus.taskId);

    // 调用API（仅触发任务，不等待完成）
    const res = await characterApi().importCharacterCsv(formData);
    
    if (res.data.success) {
      ElMessage.success('角色表导入任务已启动');
    } else {
      // 仅当接口明确返回失败时才清理
      taskStatus.progressVisible = false;
      ElMessage.error(JSON.stringify(res.data) || '导入失败');
      clearProgressTimer();
    }

    return false; // 阻止默认上传
  } catch (error) {
    ElMessage.error('导入失败');
    clearProgressTimer();
    taskStatus.progressVisible = false;
    taskStatus.loading = false;
    return false;
  }
};

// 统一进度查询函数（支持导入/导出）
const fetchTaskProgress = async () => {
  try {
    if (!taskStatus.taskId) return;

    const response = await translateApi().getTaskProgress(taskStatus.taskId);
    taskStatus.progress = response.data.progress;

    // 进度完成或取消时，清理定时器并隐藏进度条
    if (response.data.progress === 100 || response.data.progress === -1) {
      clearProgressTimer(); // 任务结束才停止查询
      if(taskStatus.type === 'import'){
        getTableData()
      }
      setTimeout(() => {
        taskStatus.progressVisible = false;
        taskStatus.loading = false;
      }, 1000);
    }
  } catch (error) {
    console.error(`获取${taskStatus.type === 'import' ? '导入' : '导出'}进度失败:`, error);
    clearProgressTimer();
    taskStatus.progressVisible = false;
    taskStatus.loading = false;
  }
};

// 清除进度定时器（统一封装）
const clearProgressTimer = () => {
  if (taskStatus.progressTimer) {
    clearInterval(taskStatus.progressTimer);
    taskStatus.progressTimer = null;
  }
};

// 新增：图片批量导入相关状态
const imageImportDialog = reactive({
  visible: false,
  fileList: [],
  selectedFiles: [] // 存储选中的文件
});

// 新增：图片批量上传组件引用
const imageBatchUploader = ref();

// 新增：处理图片批量导入的文件选择
const handleBatchFileChange = (uploadFile, uploadFiles) => {
  imageImportDialog.fileList = uploadFiles;
  imageImportDialog.selectedFiles = uploadFiles.map(f => f.raw);
};

// 新增：打开图片批量导入对话框
const openImageImportDialog = () => {
  imageImportDialog.visible = true;
  imageImportDialog.fileList = [];
  imageImportDialog.selectedFiles = [];
};

// 新增：确认图片批量导入
const confirmImageImport = async () => {
  if (imageImportDialog.selectedFiles.length === 0) {
    ElMessage.warning('请选择至少一个文件');
    return;
  }
  
  try {
    // 初始化任务状态
    taskStatus.type = 'import';
    taskStatus.loading = true;
    taskStatus.progress = 0;
    taskStatus.progressVisible = true;
    taskStatus.taskId = `image_import_${Date.now()}`;
    
    // 启动进度查询定时器

    const formData = new FormData();
    imageImportDialog.selectedFiles.forEach(file => {
      formData.append('files', file);
    });
    formData.append('taskId', taskStatus.taskId);
    formData.append('targetPath', `${configStore.config.imagesPath}\\character`);
    taskStatus.progressTimer = setInterval(() => {
      if (taskStatus.progressVisible && taskStatus.taskId) {
        fetchTaskProgress();
      }
    }, 500);
    // 调用图片批量导入API
    const res = await characterApi().importCharacterImages(formData);

    if (res.data.success) {
      ElMessage.success('图片导入任务已开始');
      imageImportDialog.visible = false;
    } else {
      ElMessage.error(res.data.message || '导入失败');
      clearProgressTimer();
      taskStatus.progressVisible = false;
    }
  } catch (error) {
    console.error('图片批量导入失败:', error);
    ElMessage.error('导入失败，请重试');
    clearProgressTimer();
    taskStatus.progressVisible = false;
    taskStatus.loading = false;
  }
};

onMounted(() => {
  getTableData()
})

</script>
